﻿//-----------------------------------------------------------------------------
// <copyright file="FileDialogImplementer.cs" company="William E. Kempf">
//     Copyright (c) William E. Kempf.
// </copyright>
//-----------------------------------------------------------------------------

namespace Onyx.Windows
{
    using System.ComponentModel;
    using System.Windows;
    using Microsoft.Win32;

    /// <summary>
    /// Provides an abstract class that provides standard implementation of
    /// <see cref="IFileDialog"/> by deferring to an instance of
    /// <see cref="Microsoft.Win32.FileDialog"/>.
    /// </summary>
    /// <typeparam name="T">The <see cref="Microsoft.Win32.FileDialog"/>
    /// type to use in the implementation.</typeparam>
    public abstract class FileDialogImplementer<T> : CommonDialogImplementer<T>, IFileDialog
        where T : FileDialog
    {
        /// <summary>
        /// Initializes a new instance of the
        /// <see cref="FileDialogImplementer{T}"/> class.
        /// </summary>
        /// <param name="owner">The owner <see cref="Window"/>.</param>
        /// <param name="dialog">The <see cref="Microsoft.Win32.FileDialog"/>
        /// to use in the implementation.</param>
        protected FileDialogImplementer(Window owner, T dialog)
            : base(owner, dialog)
        {
        }

        /// <summary>
        /// Occurs when the user selects a filename by either clicking the Open button of
        /// the OpenFileDialog or the Save button of the SaveFileDialog.
        /// </summary>
        public event CancelEventHandler FileOk
        {
            add { Dialog.FileOk += value; }
            remove { Dialog.FileOk -= value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether a file dialog automatically
        /// adds an extension to a filename if the user omits an extension.
        /// </summary>
        /// <value><see langword="true"/> if extensions are added; otherwise, <see langword="false"/>.
        /// The default value is <see langword="true"/>.</value>
        public bool AddExtension
        {
            get
            {
                return Dialog.AddExtension;
            }

            set
            {
                Dialog.AddExtension = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether a file dialog displays a
        /// warning if the user specifies a filename that does not exist.
        /// </summary>
        /// <value><see langword="true"/> if warnings are displayed; otherwise, <see langword="false"/>.
        /// The default value is <see langword="false"/>.</value>
        /// <remarks>The OpenFileDialog class sets this property to true in its
        /// constructor.</remarks>
        public bool CheckFileExists
        {
            get
            {
                return Dialog.CheckFileExists;
            }

            set
            {
                Dialog.CheckFileExists = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether warnings are displayed if the user types invalid paths and filenames.
        /// </summary>
        /// <value><see langword="true"/> if warnings are displayed; otherwise, <see langword="false"/>.
        /// The default value is <see langword="true"/>.</value>
        public bool CheckPathExists
        {
            get
            {
                return Dialog.CheckPathExists;
            }

            set
            {
                Dialog.CheckPathExists = value;
            }
        }

        /// <summary>
        /// Gets or sets a value that specifies the default extension string
        /// to use to filter the list of files that are displayed.
        /// </summary>
        /// <value>The default extension string. The default is
        /// <see cref="System.String.Empty"/>.</value>
        /// <remarks>By default, the <see cref="IFileDialog.AddExtension"/>
        /// property attempts to determine the extension to filter the displayed
        /// file list from the <see cref="IFileDialog.Filter"/> property. If the
        /// extension cannot be determined from the <see cref="IFileDialog.Filter"/>
        /// property, <see cref="IFileDialog.DefaultExt"/> will be used instead.</remarks>
        public string DefaultExt
        {
            get
            {
                return Dialog.DefaultExt;
            }

            set
            {
                Dialog.DefaultExt = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether a file dialog returns
        /// either the location of the file referenced by a shortcut or the
        /// location of the shortcut file (.lnk).
        /// </summary>
        /// <value><see langword="true"/> to return the location referenced; otherwise,
        /// <see langword="false"/>. The default value is <see langword="false"/>.</value>
        public bool DereferenceLinks
        {
            get
            {
                return Dialog.DereferenceLinks;
            }

            set
            {
                Dialog.DereferenceLinks = value;
            }
        }

        /// <summary>
        /// Gets or sets a string containing the full path of the file
        /// selected in a file dialog.
        /// </summary>
        /// <value>A String that is the full path of the file selected in the
        /// file dialog. The default is <see cref="System.String.Empty"/>.</value>
        /// <remarks>If more than one filename is selected (length of
        /// <see cref="IFileDialog.FileNames"/> is greater than one) then
        /// <see cref="IFileDialog.FileName"/> contains the first selected
        /// filename. If no filename is selected, this property contains
        /// <see cref="System.String.Empty"/> rather than <see langword="null"/>.</remarks>
        public string FileName
        {
            get
            {
                return Dialog.FileName;
            }

            set
            {
                Dialog.FileName = value;
            }
        }

        /// <summary>
        /// Gets an array that contains one filename for each selected file.
        /// </summary>
        /// <value>An array of <see cref="System.String"/> that contains one
        /// filename for each selected file. The default is an array with a
        /// single item whose value is <see cref="System.String.Empty"/>.</value>
        public string[] FileNames
        {
            get { return Dialog.FileNames; }
        }

        /// <summary>
        /// Gets or sets the filter string that determines what types of files
        /// are displayed.
        /// </summary>
        /// <value>A <see cref="System.String"/> that contains the filter. The
        /// default is <see cref="System.String.Empty"/>, which means that no
        /// filter is applied and all file types are displayed.</value>
        public string Filter
        {
            get
            {
                return Dialog.Filter;
            }

            set
            {
                Dialog.Filter = value;
            }
        }

        /// <summary>
        /// Gets or sets the index of the filter currently selected in a file
        /// dialog.
        /// </summary>
        /// <value>The <see cref="System.Int32"/> that is the index of the
        /// selected filter. The default is <c>1</c>.</value>
        /// <remarks>This index is 1-based, not 0-based, due to compatibility
        /// requirements with the underlying Win32 API.</remarks>
        public int FilterIndex
        {
            get
            {
                return Dialog.FilterIndex;
            }

            set
            {
                Dialog.FilterIndex = value;
            }
        }

        /// <summary>
        /// Gets or sets the initial directory that is displayed by a file
        /// dialog.
        /// </summary>
        /// <value>A <see cref="System.String"/> that contains the initial
        /// directory. The default is <see cref="System.String.Empty"/>.</value>
        /// <remarks>If there is no initial directory set, this property will
        /// contain <see cref="System.String.Empty"/> rather than a <see langword="null"/>
        /// string.</remarks>
        public string InitialDirectory
        {
            get
            {
                return Dialog.InitialDirectory;
            }

            set
            {
                Dialog.InitialDirectory = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the file dialog should restore its current directory to the original
        /// value before a user changes directory to search for files.
        /// </summary>
        /// <value><see langword="true"/> if directory should be restored after a search; otherwise,
        /// <see lagnword="false"/>. The default value is <see langword="false"/>.</value>
        /// <remarks><see cref="IFileDialog.RestoreDirectory"/> is only valid for <see cref="ISaveFileDialog"/>; it has
        /// no effect when set on <see cref="IOpenFileDialog"/>.</remarks>
        public bool RestoreDirectory
        {
            get
            {
                return Dialog.RestoreDirectory;
            }

            set
            {
                Dialog.RestoreDirectory = value;
            }
        }

        /// <summary>
        /// Gets a string that only contains the filename for the selected
        /// file.
        /// </summary>
        /// <value>A <see cref="System.String"/> that only contains the
        /// filename for the selected file. The default is
        /// <see cref="System.String.Empty"/>, which is also the value when
        /// either no file is selected or a directory is selected.</value>
        /// <remarks>
        /// <para>This value is the <see cref="IFileDialog.FileName"/> with
        /// all path information removed. Removing the paths makes the value
        /// appropriate for use in partial trust applications, since it prevents
        /// applications from discovering information about the local file
        /// system.</para>
        /// <para>If more than one filename is selected (length of
        /// <see cref="IFileDialog.SafeFileNames"/> is greater than one) then
        /// this property contains only the first selected filename.</para>
        /// </remarks>
        public string SafeFileName
        {
            get { return Dialog.SafeFileName; }
        }

        /// <summary>
        /// Gets an array that contains one safe file name for each selected file.
        /// </summary>
        /// <value>An array of <see cref="System.String"/> that contains one safe
        /// file name for each selected file. The default is an array with a single
        /// item whose value is <see cref="System.String.Empty"/>.</value>
        /// <remarks>See <see cref="IFileDialog.SafeFileName"/>.</remarks>
        public string[] SafeFileNames
        {
            get { return Dialog.SafeFileNames; }
        }

        /// <summary>
        /// Gets or sets the text that appears in the title bar of a file dialog.
        /// </summary>
        /// <value>A <see cref="System.String"/> that is the text that appears in
        /// the title bar of a file dialog. The default is
        /// <see cref="System.String.Empty"/>.</value>
        /// <remarks>If Title is null or <see cref="System.String.Empty"/>, a
        /// default, localized value is used, such as "Save As" or "Open".</remarks>
        public string Title
        {
            get
            {
                return Dialog.Title;
            }

            set
            {
                Dialog.Title = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the dialog accepts only valid
        /// Win32 filenames.
        /// </summary>
        /// <value><see langword="true"/> if warnings will be shown when an invalid filename
        /// is provided; otherwise, <see langword="false"/>. The default value is <see langword="false"/>.</value>
        public bool ValidateNames
        {
            get
            {
                return Dialog.ValidateNames;
            }

            set
            {
                Dialog.ValidateNames = value;
            }
        }
    }
}
